import fs from 'fs';
import path from 'path';
import { globby } from 'globby';
import * as parser from '@babel/parser';
import _traverse from '@babel/traverse';
import t from '@babel/types';
import _generator from '@babel/generator';

const traverse = _traverse.default;
const generator = _generator.default;

// 核心转换函数
function convertToClass(code) {
  const ast = parser.parse(code, {
    sourceType: 'module',
    plugins: ['jsx'],
    attachComment: true
  });

  let className = null;
  let constructorNode = null;
  const prototypeMethods = [];
  const staticMethods = [];
  let exportDefaultNode = null;

  // 处理构造函数
  traverse(ast, {
    FunctionDeclaration(path) {
      if (t.isIdentifier(path.node.id)) {
        className = path.node.id.name;

        constructorNode = t.classMethod(
          'constructor',
          t.identifier('constructor'),
          path.node.params,
          path.node.body
        );

        // 保留注释
        constructorNode.leadingComments = path.node.leadingComments;
        constructorNode.innerComments = path.node.innerComments;
        constructorNode.trailingComments = path.node.trailingComments;

        path.remove();
      }
    }
  });

  // 处理原型方法
  traverse(ast, {
    AssignmentExpression(path) {
      const { left, right } = path.node;
      if (
        t.isMemberExpression(left) &&
        t.isMemberExpression(left.object) &&
        t.isIdentifier(left.object.object) &&
        t.isIdentifier(left.object.property, { name: 'prototype' }) &&
        t.isIdentifier(left.property)
      ) {
        const methodName = left.property.name;
        const methodClass = left.object.object.name;

        if (className && methodClass === className) {
          const classMethod = t.classMethod(
            'method',
            t.identifier(methodName),
            right.params,
            right.body
          );

          // 保留注释
          classMethod.leadingComments = path.node.leadingComments;
          classMethod.innerComments = path.node.innerComments;
          classMethod.trailingComments = path.node.trailingComments;

          prototypeMethods.push(classMethod);
          path.remove();
        }
      }
    }
  });

  // 处理静态方法
  traverse(ast, {
    AssignmentExpression(path) {
      const { left, right } = path.node;
      if (
        t.isMemberExpression(left) &&
        t.isIdentifier(left.object) &&
        t.isIdentifier(left.property)
      ) {
        const methodName = left.property.name;
        const methodClass = left.object.name;

        if (className && methodClass === className) {
          const staticMethod = t.classMethod(
            'method',
            t.identifier(methodName),
            right.params,
            right.body
          );

          // 设为静态方法
          staticMethod.static = true;

          // 保留注释
          staticMethod.leadingComments = path.node.leadingComments;
          staticMethod.innerComments = path.node.innerComments;
          staticMethod.trailingComments = path.node.trailingComments;

          staticMethods.push(staticMethod);
          path.remove();
        }
      }
    }
  });

  // 处理导出语句
  traverse(ast, {
    ExportDefaultDeclaration(path) {
      if (t.isIdentifier(path.node.declaration)) {
        exportDefaultNode = t.exportDefaultDeclaration(
          t.identifier(path.node.declaration.name)
        );

        // 保留注释
        exportDefaultNode.leadingComments = path.node.leadingComments;
        exportDefaultNode.innerComments = path.node.innerComments;
        exportDefaultNode.trailingComments = path.node.trailingComments;

        path.remove();
      }
    }
  });

  // 如果没有找到类定义，返回原始代码
  if (!className) return code;

  // 构建类节点
  const classBody = [];
  if (constructorNode) classBody.push(constructorNode);
  classBody.push(...prototypeMethods, ...staticMethods);

  const classDeclaration = t.classDeclaration(
    t.identifier(className),
    null,
    t.classBody(classBody)
  );

  // 保留文件顶部注释
  if (ast.program.body.length > 0 && ast.program.body[0].leadingComments) {
    classDeclaration.leadingComments = ast.program.body[0].leadingComments;
  }

  // 更新AST
  const newBody = [];

  // 添加类声明
  newBody.push(classDeclaration);

  // 添加导出语句
  if (exportDefaultNode) newBody.push(exportDefaultNode);

  ast.program.body = newBody;

  // 生成代码并保留格式
  return generator(ast, {
    retainLines: true,
    comments: true,
    jsescOption: { minimal: true }
  }).code;
}

const FILE_PATTERN = '**/*.js'; // 匹配所有子目录的 JS 文件 
// 批量转换文件
async function convertFiles(srcDir, destDir) {
  try {
    const files = await globby([FILE_PATTERN], { cwd: srcDir });

    for (const file of files) {
      const srcPath = path.resolve(path.join(srcDir, file));
      const relativePath = path.relative(srcDir, srcPath);
      const destPath = path.join(destDir, relativePath);

      try {
        const code = fs.readFileSync(srcPath, 'utf-8');
        const transformed = convertToClass(code);

        // 确保目录存在
        fs.mkdirSync(path.dirname(destPath), { recursive: true });

        fs.writeFileSync(destPath, transformed);
        console.log(`✅ 转换成功: ${relativePath}`);
      } catch (error) {
        console.error(`❌ 转换失败 [${relativePath}]: ${error.message}`);
      }
    }

    console.log('✨ 所有文件转换完成!');
  } catch (error) {
    console.error('🚨 目录处理错误:', error.message);
  }
}

// 命令行参数处理
let [src, dest] = process.argv.slice(2);
if (!src || !dest) {
  console.log('用法: node convert.mjs <源目录> <目标目录>');
  // process.exit(1);
  src = './src';
  dest = './dist';
}

// 执行转换
convertFiles(path.resolve(src), path.resolve(dest));